var express = require('express');
var router = express.Router();
const fs = require('fs');
const path = require('path');
const nodemailer = require('nodemailer')
const UniSMS = require('unisms').default
var {loginmodel} = require('../../model/model')
var jwt = require("jsonwebtoken")
const expressJWT = require('express-jwt')
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const tencentcloud = require("tencentcloud-sdk-nodejs-iai");
var  {Usermodel,Rolemodel,Loginmodel,Permissionsmodel,ListModel,cateModel,} = require('../../model/model')
//添加账号
router.post('/addloginrr',async (req, res) => {
    await Loginmodel.create(req.body)
    res.send({code:200})
})
//获取分类
router.get('/getcate',async (req, res) => {
    const list = await cateModel.find()
    res.send({list})
})
//添加商品数据
router.post('/addlist',async (req, res) => {
  await ListModel.create(req.body)
  res.send({code:200})
})
//搜索账号
router.get('/ssloginr',async (req, res) => {
    let {name} = req.query
    let list = await Loginmodel.find({username:name})
    res.send({list})
})
//搜索权限
router.get('/ssrole',async (req, res) => {
  let {name} = req.query
    let list = await Rolemodel.find({name:name})
    res.send({list})
})
//权限渲染接口
router.get('/getPermissions',async (req, res) => {
  let {_id} = req.query
  let user = await Usermodel.find({ _id: _id }) //获取用户信息
  let COS = await Rolemodel.find({ _id: user[0].cid }) //获取用户身份
  let quan_list = await Permissionsmodel.find().lean() //获取权限列表

  let list = []
  COS[0].Permissions.forEach(ID => { //获取用户权限
    quan_list.forEach(item => { //获取权限列表
      if (String(ID) == String(item._id)) { //判断权限列表是否包含用户权限
        list.push(item) //如果包含，则添加到list中
      }
    })
  })

  let quanobj = {} //创建一个空对象
  list.forEach(item => {
    quanobj[item._id] = item //将权限列表添加到空对象中
  })
  let aaa = []
  list.forEach(item => {
    if (!item.pid) {
      aaa.push(item) //如果权限列表中不存在pid，则将权限列表添加到aaa中
    } else {
      if (!quanobj[item.pid]['children']) {
        quanobj[item.pid]['children'] = [] //如果权限列表中存在pid，则将权限列表添加到children中
      }
      if (quanobj[item.pid]) {
        quanobj[item.pid]['children'].push(item) //如果权限列表中存在pid，则将权限列表添加到children中
      }
    }
  })
  res.send({
    cos_name: COS[0].name,
    info_list: aaa,
    code: 200
  })
})

router.post('/addPermissions', async (req, res) => {
  await Permissionsmodel.create(req.body)
  res.send('ok')
})
router.post('/login', async (req, res) => {
      await Usermodel.create(req.body)
      res.send('ok')
})
router.post('/addrole', async (req, res) => {
  await Rolemodel.create(req.body)
  res.send('ok')
})

router.get('/getrole', async (req, res) => {
  let list = await Rolemodel.find()
  res.send({list})
})

router.post('/addloginr', async (req, res) => {
  await Loginmodel.create(req.body)
  res.send('ok')
})
router.get('/getloginr', async (req, res) => {
  let list = await Loginmodel.find().populate('pid')
  res.send({list})
})
router.post('/getlogin', async (req, res) => { 
  let {username,password} = req.body
  const secretKey = 'kanno&fangbaobao'
  let result = await Usermodel.findOne({username,password})
  if(result){
    res.send({code:200,msg:'登录成功',result,token:jwt.sign({username:result.username},secretKey,{expiresIn:'30s'})})
  }else{
    res.send({code:400,msg:'登录失败'})
  }
})

//用于判断邮箱是否已经注册
router.get('/getcode', async (req, res) => {
  let {username} = req.query
  let result = await Usermodel.findOne({username})
  if(result){
    res.send({code:400,msg:'邮箱已注册'})
  }else{
    res.send({code:200,msg:'邮箱未注册'})
  }
})
let transporter = nodemailer.createTransport({
    service: 'qq', // 类型qq邮箱
    port: 465,
    secure: true,
    auth: { user: '3022425620@qq.com', pass: 'ltxycosfmgajdced' }
  })
  function sendMail(email, code, call) {
    // 发送的配置项
    let mailOptions = {
      from: '3022425620@qq.com', // 发送者
      to: email, // 接受者,可以同时发送多个,以逗号隔开
      subject: 'vue3admin', // 标题
      html: `<h2>欢迎登录:本次的验证码是${code}</h2>`
    }
    transporter.sendMail(mailOptions, (error, info) => {
      if (error) {
        call(false)
      } else {
        call(true) //因为是异步 所有需要回调函数通知成功结果
      }
    })
  }
  // 根据邮箱获取code
  // 设置一个定时器 定时清除check和邮箱的对应关系
  const check = {}
  router.get('/code', async (req, res) =>{
    // 获取邮箱
    if (!req.query.email) return res.send({ code: 400, message: '缺少必填参数' })
    let email = req.query.email
    let list = await Usermodel.find({username: email})
    if(list.length > 0){
      res.send({code:400,msg:'该邮箱已被注册'})
    }else{
      let code = Math.random().toString().slice(2, 6)
    check[email] = code // 邮箱和验证码对应关系
    sendMail(email, code, function (result) {
      if (result) {
        // 获取邮箱成功 开启定时器
        setTimeout(() => {
          delete check[email]
          console.log(`成功清除${email}code的对应关系`)
        }, 60000)
        res.send({ code: code, message: '验证码发送成功' })
      } else {
        res.send({ code: 400, message: '验证码发送失败' })
      }
    })
    }
  })
  //用于邮箱的修改密码
  router.get('/codes', async (req, res) =>{
    // 获取邮箱
    if (!req.query.email) return res.send({ code: 400, message: '缺少必填参数' })
    let email = req.query.email
    let list = await Usermodel.find({username: email})

    if(list.length > 0){
      let code = Math.random().toString().slice(2, 6)
    check[email] = code // 邮箱和验证码对应关系
    sendMail(email, code, function (result) {
      if (result) {
        // 获取邮箱成功 开启定时器
        setTimeout(() => {
          delete check[email]
          console.log(`成功清除${email}code的对应关系`)
        }, 60000)
        res.send({ code: code, message: '验证码发送成功' })
      } else {
        res.send({ code: 400, message: '验证码发送失败' })
      }
    })
      
    }else{
      res.send({code:400,msg:'该邮箱未被注册'})
    }
  })
  
  // 注册用户
  router.post('/register', async function (req, res, next) {
    // 必填账号密码邮箱
    const { username, password, code } = req.body
    if (!username || !password  || !code) return res.send({ code: 400, message: '缺少必填参数' })
    try {
      //判断邮箱验证码是否正确 失效时间1分钟
      if (check[email] !== code) return res.send({ code: 400, message: '验证码错误' })
      await Usermodel.create({ username,password}) // 创建新用户
      res.send({ code: 200, message: '注册成功' })
    } catch (error) {
      res.send({ code: 500, message: error })
    }
  })

  // 邮箱修改密码
  router.post('/uplregister', async (req,res) =>{
    // 必填账号密码邮箱
    const { username, password,code } = req.body
    if (!username || !password  || !code) return res.send({ code: 400, message: '缺少必填参数' })
    try {
      // //判断邮箱验证码是否正确 失效时间1分钟
      // if (check[email] !== code) return res.send({ code: 400, message: '验证码错误' })  
      const list = await Usermodel.find({ username }) 
      list[0].password = password
      list[0].save()
      res.send({ code: 200, message: '修改成功' })
    } catch (error) {
      res.send({ code: 500, message: error })
    }
  })
//通过手机号注册
router.post('/addphone', async (req, res) => {
  const { username, password} = req.body
  if (!username || !password) return res.send({ code: 400, message: '缺少必填参数' })
  try {
    await Usermodel.create({ username, password }) // 创建新用户
    res.send({ code: 200, message: '注册成功' })
  }catch (error) {
    res.send({ code: 500, message: error })
  }
})
//手机号发送短信
  router.get('/getphone', async (req, res) => {
    // 初始化
    const client = new UniSMS({
      accessKeyId: 'kFPQui4yfbycyfEKP2cEXJyqK8gUQ7b2AesoHNRBQyR9GH9Ce',  //当你实名认证之后就会自动生成ID，直接复制就行
    })
   
    //接收前端发送过来的手机号
    const { phone } = req.query
    //判断该手机号是否已经注册
    const user = await Usermodel.findOne({ username: phone })
    if (user){
      return res.send({ code: 400, message: '该手机号已注册' })
    }else{
         //生成随机的四位数验证码，也可以修改成其他几位数验证码
    const len = Math.floor(1000 + Math.random() * 9000)
  
    // 发送短信
    client.send({
      to: phone,
      signature: '姜思兵',
      templateId: 'pub_verif_short2', //短信报备中模板管理，在里面随便复制一个通道就可以
      templateData: {
        code: len,
      },
    })
      .then(ret => {
        res.json({ code: ret.code,len:len}); //向前端发送生成的验证码
      })
      .catch(e => {
        console.error(e)
      })
    }
 
  })
  //手机号发送短信 用来修改密码
  router.get('/getphones', async (req, res) => {
    // 初始化
    const client = new UniSMS({
      accessKeyId: 'kFPQui4yfbycyfEKP2cEXJyqK8gUQ7b2AesoHNRBQyR9GH9Ce',  //当你实名认证之后就会自动生成ID，直接复制就行
    })
   
    //接收前端发送过来的手机号
    const { phone } = req.query
    //判断该手机号是否已经注册
    const user = await Usermodel.findOne({ username: phone })
    if (user){
           //生成随机的四位数验证码，也可以修改成其他几位数验证码
    const len = Math.floor(1000 + Math.random() * 9000)
  
    // 发送短信
    client.send({
      to: phone,
      signature: '姜思兵',
      templateId: 'pub_verif_short2', //短信报备中模板管理，在里面随便复制一个通道就可以
      templateData: {
        code: len,
      },
    })
      .then(ret => {
        res.json({ code: ret.code,len:len}); //向前端发送生成的验证码
      })
      .catch(e => {
        console.error(e)
      })
      
    }else{
      return res.send({ code: 400, message: '该手机号未被注册' })
    }
 
  })
//用于手机号修改密码
router.post('/uplphone', async (req, res) => {
  const { username, password} = req.body
  if (!username || !password) return res.send({ code: 400, message: '缺少必填参数' })
  try {
    const list = await Usermodel.find({ username }) 
    list[0].password = password
    await list[0].save()
    res.send({ code: 200, message: '修改成功' })
  }catch (error) {
    res.send({ code: 500, message: error })
  }
})
  //人脸识别登录
router.post('/faceLogin', async (req, res) => {
  //获取前端传来的base64
  let b64 = req.body.b64

  const IaiClient = tencentcloud.iai.v20200303.Client;

  const clientConfig = {
      credential: {
          //自己的腾讯secretId
          secretId: "AKID30mSxGMEvQhkfOuDIVXLwMdia7Xpv7EA",
          //自己的腾讯密匙
          secretKey: "naAbwHBvSmslQr56wZzB3odDk7NSZZO1",
      },
      region: "ap-beijing",  //地域参数（华北地区北京）
      profile: {
          httpProfile: {
              endpoint: "iai.tencentcloudapi.com",
          },
      },
  };

  const client = new IaiClient(clientConfig);

  const params = {
      "GroupIds": [  //你创建的人员库ID
          "040510"
      ],
      "Image": b64,  //图片的base64格式编码
      "NeedPersonInfo": 1,  //是否返回人员具体信息。0 为关闭，1 为开启。默认为 0。
      "QualityControl": 0,  //图片质量控制。 0: 不进行控制； 1:较低的质量要求
      "FaceMatchThreshold": 80,  //人脸对比度设置为大于85才可
  };

  let doc = await client.SearchFaces(params)
  //doc为人脸识别后的返回信息
  console.log(doc, 'doc');
  if (doc.Results[0].Candidates.length != 0) {  //表示当前人脸库有该人员
      let personName = doc.Results[0].Candidates[0].PersonName  //拿到该人员的名称
      let result = await Usermodel.findOne({ username: personName })  //查询数据库中是否存在该人员
      //生成token
      let token = jwt.sign({ "name": personName }, "face", { expiresIn: '1d' })
      res.send({
          code: 200,
          msg: "登录成功！",
          token,
          result
      })

  } else {
      res.send({
          code: 401,
          msg: '人脸库无此人！'
      })
      return false
  }

})

// 检查上传目录是否存在，如果不存在则创建
const uploadDir = path.join(__dirname, 'uploads');// 上传目录
if (!fs.existsSync(uploadDir)) {
  fs.mkdirSync(uploadDir);// 创建目录
}

// 文件分片上传接口
router.post('/upload', (req, res) => {
  const fileName = decodeURIComponent(req.headers['file-name']); // 对文件名进行解码
  const filePath = path.join(uploadDir, `${fileName}.${req.headers['file-index']}`);// 获取文件路径

  const writeStream = fs.createWriteStream(filePath);// 创建写入流
  req.pipe(writeStream);// 将请求数据流写入文件

  writeStream.on('finish', () => {
    console.log(`分片 ${req.headers['file-index']} 上传成功，路径: ${filePath}`);
    res.status(200).send('分片上传成功');
  });

  writeStream.on('error', (err) => {
    console.error(`分片 ${req.headers['file-index']} 上传失败:`, err);
    res.status(500).send('分片上传失败');
  });
});



// 查询已上传的分片
router.get('/uploaded-chunks', (req, res) => {
  const fileName = decodeURIComponent(req.query.fileName); // 对文件名进行解码
  const chunks = [];
  // 遍历文件夹，查找已存在的分片
  fs.readdir(uploadDir, (err, files) => {
    if (err) {
      res.status(500).send('读取文件夹失败');
      return;
    }

    files.forEach(file => {
      if (file.startsWith(`${fileName}.`)) {
        const index = file.split('.').slice(-1)[0];// 获取文件名中的索引部分
        chunks.push(index);// 将索引添加到chunks数组中
      }
    });

    res.status(200).json(chunks);// 返回已上传的分片列表
  });
});



// 合并分片
function mergeChunks(totalChunks, uploadDir, fileName, res) {
  let chunksWritten = 0;
  let hasError = false;
  const writeStream = fs.createWriteStream(path.join(uploadDir, fileName));
  function processChunk(i) {// 合并分片
    if (i >= totalChunks || hasError) {// 如果所有分片都处理完毕或者有错误发生，则停止处理
      return;
    }
    const chunkPath = path.join(uploadDir, `${fileName}.${i}`);// 分片文件路径
    if (!fs.existsSync(chunkPath)) {
      console.error(`分片 ${i} 不存在，路径: ${chunkPath}`);// 如果分片文件不存在，则输出错误信息
      res.status(404).send(`分片 ${i} 不存在`); // 返回错误信息
      hasError = true;
      return;
    }

    const readStream = fs.createReadStream(chunkPath);// 创建分片文件的读取流
    readStream.pipe(writeStream, { end: false });// 将分片文件的内容写入合并文件中
    readStream.on('end', () => {
      fs.unlinkSync(chunkPath);
      console.log(`分片 ${i} 合并完成，路径: ${chunkPath}`);
      chunksWritten++;// 分片处理完成，计数器加1

      if (chunksWritten === totalChunks) {// 如果所有分片都处理完毕，则关闭合并文件的写入流
        writeStream.end();
        writeStream.on('finish', () => {
          console.log('所有分片合并完成');
          res.status(200).send('文件合并成功');
        });
      } else {
        processChunk(i + 1);
      }
    });

    readStream.on('error', (err) => {
      console.error(`分片 ${i} 读取失败:`, err);
      hasError = true;// 如果有错误发生，则设置错误标志
      res.status(500).send(`分片 ${i} 读取失败`);
      writeStream.destroy(); // 关闭写入流
    });
  }

  processChunk(0);
}


// 文件合并接口
router.post('/merge', (req, res) => {
  const fileName = decodeURIComponent(req.body.fileName); // 对文件名进行解码
  const totalChunks = req.body.totalChunks;// 文件总片数
  const originalChecksum = req.body.originalChecksum; // 原始文件校验和
  const filePath = path.join(uploadDir, fileName);// 文件路径
  const writeStream = fs.createWriteStream(filePath);// 文件路径
  let chunksWritten = 0;
  const num = 0;
  let hasError = false;// 标记是否有错误

  // 准备一个函数来处理流的结束情况
  const checkFinish = () => {
    if (chunksWritten === totalChunks && !hasError) {
      writeStream.end(); // 所有分片写入完成，关闭文件流
    }
  };

  mergeChunks(totalChunks, uploadDir, fileName, res) //调用合并事件

  writeStream.on('finish', async () => { // 文件流写入完成 
    console.log(`文件 ${fileName} 合并完成，路径: ${filePath}`);
    res.status(200).send('文件合并完成');
    // 校验文件大小
    try {
      const mergedChecksum = await calculateChecksum(filePath);
      if (mergedChecksum === originalChecksum) {
        console.log('文件校验和匹配，文件合并成功');
        // res.status(200).send('文件合并完成');
      } else {
        console.error('文件校验和不匹配，文件可能已损坏');
        // res.status(500).send('文件校验和不匹配，文件可能已损坏');
      }
    } catch (err) {
      console.error('校验和计算失败:', err);
      //   res.status(500).send('校验和计算失败');
    }
  });


  writeStream.on('error', (err) => {
    console.error('文件合并失败:', err);
    res.status(500).send('文件合并失败');
  });
});

module.exports = router;
